package mybatis.hr.dao;

import java.util.List;
import java.util.Map;

import mybatis.hr.domain.Department;
import mybatis.hr.util.DatabaseManager;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

//싱글톤 패턴으로 구현
public class DepartmentDAO {
	private static DepartmentDAO instance;
	private SqlSessionFactory factory;
	private DepartmentDAO(){
		DatabaseManager manager = DatabaseManager.getInstance();
		factory = manager.getSqlSessionFactory();
	}
	
	public static DepartmentDAO getInstance(){
		if(instance==null){
			instance = new DepartmentDAO();
		}
		return instance;
	}
	/*
	 * SqlSession
	 *	- sql문을 실행 메소드를 제공하는 객체(insert(), update(), selectList(), selectMap())	
	 *		- unchecked 계열의 Exception을 던지므로 try 구문안에 작성
	 *	- transaction을 처리
	 *	- 업무 흐름당 하나씩 만들어 사용
	 * 코딩 패턴
	 * 	1. SqlSessionFactory로 부터 SqlSession객체 조회 - DB 업무 시작
	 * 	2. sql문 실행
	 * 		2-1. DML(insert/update/delete)인 경우 commit() 처리
	 * 	3. 업무 종료 처리 (session 종료) - close() : 자원 반납. finally에서 처리
	 */
	public int insertDepartment(Department department){
		SqlSession session = factory.openSession();
		
		try{
			//매개변수 : 1, sql문 id, 2.?에 넣을 값 (여러개일 경우 맵이나 DO를 통해 전달)
			int cnt = session.insert("hr.department.insertDepartment", department);
			//commit 처리
			session.commit();
			return cnt;
		}finally{
			session.close();
		}
	}
	
	public int updateDepartment(Department department) {
		//1. SqlSession 조회
		SqlSession session = factory.openSession();
		try{
		//2. 쿼리 전송 - DML : commit()
		int cnt = session.update("hr.department.updateDepartment",department);
		session.commit();
		return cnt;
		}finally{
		//3. close
			session.close();
		}
	}
	
	public int deleteDeparmentByNo(int departmentNo)	{
		SqlSession session = factory.openSession();
		try {
			int cnt = session.delete("hr.department.deleteDepartmentByNo", departmentNo);
			session.commit();
			return cnt;
		}finally{
			session.close();
		}
	}
	
	public int deleteDepartmentByLocation(String location) {
		SqlSession session = factory.openSession();
		try{
			int cnt = session.delete("hr.department.deleteDepartmentByLocation", location);
			//xml에서 설정한 쿼리아이디인데 앞에 namespace를 꼭 붙여야한다
			session.commit();
			return cnt;
			
		}finally{
			session.close();
		}
	}
	
	/*
	 * sqlSession.selectOne() : T(resultType선언 타입)
	 * 		-조회 row가 하나일 경우
	 * sqlSession.selectList() : List<E> E(resultType선언 타입)
	 * 		-조회 row가 하나 이상인 경우(조회결과를 List로 묶어서 리턴)
	 * sqlSession.selectMap() : Map<K,V>
	 * 		-조회 row가 하나 이상인 경우(조회결과를 Map로 묶어서 리턴)
	 */
	
	public Department selectDepartmentByNo(int no) {
		SqlSession session = factory.openSession();
		try{
			//department객체로 직접 조회하니까
			Department dept = session.selectOne("hr.department.selectDepartmentByNo", no);
			//select인경우 commit()이 필요없다.
			return dept;
		}finally{
			session.close();
		}
	}
	
	public List<Department> selectDepartmentList() { //제너릭 처리는 xml에서 department객체니까 department로 
		SqlSession session = factory.openSession();
		try{
			return session.selectList("hr.department.selectDepartmentList"); // List 로 묶어주는 역할 / 매개변수 없음(?없음)
		}finally{
			session.close();
		}
	}
	
	public Map<Integer, Department> selectDepartmentList_Map() {
		SqlSession session = factory.openSession();
		try{
			//2번 - 키로 사용할 property
			return session.selectMap("hr.department.selectDepartmentList", "departmentNo");
			//selectMap(String id, Object parameter, String key) -> ?가 있는 경우
		}finally {
			session.close();
		}
	}
	
	public List<Department> selectDepartmentByLocation_List(String location) {
		SqlSession session = factory.openSession();
		try{
			return session.selectList("hr.department.selectDepartmentByLocation_List", location);
		}finally{
			session.close();
		}
	}
	 
	public Map<Integer, Department> selectDepartmentByLocation_Map(String location) {
		SqlSession session = factory.openSession();
		try{
			return session.selectMap("hr.department.selectDepartmentByLocation_List", location, "departmentNo");
		}finally{
			session.close();
		}
	}
	
	public List<Department> selectDepartmentByName(String departmentName) {
		SqlSession session = factory.openSession();
		try{
			return session.selectList("hr.department.selectDepartmentByName", departmentName);
		}finally{
			session.close();
		}
	}
	
	public Department selectDepartmentJoinEmployee(int departmentNo) {
		SqlSession session = factory.openSession();
		try{
			return session.selectOne("hr.department.selectDepartmentJoinEmployee", departmentNo);
		}finally {
			session.close();
		}
	}

}
